#pragma once
#include <vector>
#include "detail.hpp"
#include "fields.hpp"
#include "abstract.hpp"

namespace myrpc{
    // 根据基础消息基类派生成Json格式的消息子类
    class JsonMessage : public BaseMessage {
    public:
        using ptr = std::shared_ptr<JsonMessage>;
        virtual std::string serialize() override {
            std::string body;
            bool ret = JsonUtil::serialize(_msg_body, body);
            if (ret == false){
                return std::string();
            }
            return body;
        }
        virtual bool unserialize(const std::string &body) override {
            return JsonUtil::unserialize(body, _msg_body);
        }

    protected:
        Json::Value _msg_body;
    };

    // 由Json格式的消息子类继续派生出Json格式请求消息子类
    class JsonRequest : public JsonMessage {
    public:
        using ptr = std::shared_ptr<JsonRequest>;
    };

    // 由Json格式请求消息子类继续派生成RPC请求子类
    class RpcRequest : public JsonRequest {
    public:
        using ptr = std::shared_ptr<RpcRequest>;
        virtual bool check() override {
            if (_msg_body[KEY_METHOD].isNull() == true || _msg_body[KEY_METHOD].isString() == false){
                root_logger->ERROR("RPC请求中缺少方法名(method)或字段类型错误!");
                return false;
            }
            if (_msg_body[KEY_PARAMS].isNull() == true || _msg_body[KEY_PARAMS].isObject() == false){
                root_logger->ERROR("RPC请求中缺少参数(params)或字段类型错误!");
                return false;
            }
            return true;
        }

        void setMethod(const std::string &method){
            _msg_body[KEY_METHOD] = method;
        }
        std::string getMethod(){
            return _msg_body[KEY_METHOD].asString();
        }
        void setParameters(const Json::Value &parameters){
            _msg_body[KEY_PARAMS] = parameters;
        }
        Json::Value getParameters(){
            return _msg_body[KEY_PARAMS];
        }
    };

    // 由Json格式请求消息子类继续派生成主题请求子类
    class TopicRequest : public JsonRequest {
    public:
        using ptr = std::shared_ptr<TopicRequest>;
        virtual bool check() override {
            if (_msg_body[KEY_TOPIC_KEY].isNull() == true || _msg_body[KEY_TOPIC_KEY].isString() == false){
                root_logger->ERROR("主题请求中缺少主题名(topic_key)或字段类型错误!");
                return false;
            }
            if (_msg_body[KEY_OPTYPE].isNull() == true || _msg_body[KEY_OPTYPE].isIntegral() == false){
                root_logger->ERROR("主题请求中缺少操作类型(optype)或字段类型错误!");
                return false;
            }
            // 发布主题时 才需要用到主题消息部分 (修正逻辑优先级)
            if (_msg_body[KEY_OPTYPE] == static_cast<int>(TopicOpType::TOPIC_PUBLISH) &&
                (_msg_body[KEY_TOPIC_MSG].isNull() == true || _msg_body[KEY_TOPIC_MSG].isString() == false))
            {
                root_logger->ERROR("主题发布请求中缺少主题消息(topic_msg)或字段类型错误!");
                return false;
            }
            return true;
        }
    
        void setTopicKey(const std::string &topickey){
            _msg_body[KEY_TOPIC_KEY] = topickey;
        }
        std::string getTopicKey(){
            return _msg_body[KEY_TOPIC_KEY].asString();
        }
        void setTopicOptype(const TopicOpType &topicoptype){
            _msg_body[KEY_OPTYPE] = static_cast<int>(topicoptype);
        }
        TopicOpType getTopicOpType(){
            return static_cast<TopicOpType>(_msg_body[KEY_OPTYPE].asInt());
        }
        // 主题消息是主题发布操作独有的字段
        void setTopicMsg(const std::string &topicmsg){
            _msg_body[KEY_TOPIC_MSG] = topicmsg;
        }
        std::string getTopicMsg(){
            return _msg_body[KEY_TOPIC_MSG].asString();
        }
    };
 
    // 主机信息结构
    using Address = std::pair<std::string, int>;
    // 由Json格式请求消息子类继续派生成服务请求子类
    class ServiceRequest : public JsonRequest {
    public:
        using ptr = std::shared_ptr<ServiceRequest>;
        virtual bool check() override {
            if (_msg_body[KEY_METHOD].isNull() == true || _msg_body[KEY_METHOD].isString() == false){
                root_logger->ERROR("服务请求中缺少方法名(method)或字段类型错误!");
                return false;
            }
            if (_msg_body[KEY_OPTYPE].isNull() == true || _msg_body[KEY_OPTYPE].isIntegral() == false){
                root_logger->ERROR("服务请求中缺少操作类型(optype)或字段类型错误!");
                return false;
            }
            // 除了服务发现请求 其余的服务注册 服务上线 服务下线都需要用到主机信息部分
            if (_msg_body[KEY_OPTYPE].asInt() != static_cast<int>(ServiceOpType::SERVICE_DISCOVERY) &&
                (_msg_body[KEY_HOST].isNull() == true || _msg_body[KEY_HOST].isObject() == false ||
                     _msg_body[KEY_HOST][KEY_HOST_IP].isNull() == true || _msg_body[KEY_HOST][KEY_HOST_IP].isString() == false ||
                     _msg_body[KEY_HOST][KEY_HOST_PORT].isNull() == true || _msg_body[KEY_HOST][KEY_HOST_PORT].isInt() == false))
            {
                root_logger->ERROR("服务请求中缺少主机信息(host)或字段类型错误!");
                return false;
            }
            return true;
        }
        
        void setMethod(const std::string &method){
            _msg_body[KEY_METHOD] = method;
        }
        std::string getMethod(){
            return _msg_body[KEY_METHOD].asString();
        }
        void setHost(const Address &host){
            Json::Value Host;
            Host[KEY_HOST_IP] = host.first;
            Host[KEY_HOST_PORT] = host.second;
            _msg_body[KEY_HOST] = Host;
        }
        Address getHost(){
            Address host;
            host.first = _msg_body[KEY_HOST][KEY_HOST_IP].asString();
            host.second=_msg_body[KEY_HOST][KEY_HOST_PORT].asInt();
            return host;
        }
        void setServiceOptype(const ServiceOpType &optype){
            _msg_body[KEY_OPTYPE] = static_cast<int>(optype);
        }
        ServiceOpType getServiceOpType(){
            return static_cast<ServiceOpType>(_msg_body[KEY_OPTYPE].asInt());
        }
    };
    
    // 由Json格式的消息子类继续派生出Json格式响应消息子类
    class JsonResponse : public JsonMessage {
    public:
        using ptr = std::shared_ptr<JsonResponse>;

        // 所有响应子类中都存在RCode响应码字段 所以直接放在响应基类中进行检查和设置 
        // 由派生类再根据特殊需要进行重写和添加
        virtual bool check() override {
            if (_msg_body[KEY_RCODE].isNull() == true || _msg_body[KEY_RCODE].isIntegral() == false){
                root_logger->ERROR("响应消息中缺少响应码(rcode)或字段类型错误!");
                return false;
            }
            return true;
        }
        
        virtual RCode getRCode(){
            return static_cast<RCode>(_msg_body[KEY_RCODE].asInt());
        }
        virtual void setRCode(RCode rcode){
            _msg_body[KEY_RCODE] = static_cast<int>(rcode);
        }
    };

    // 由Json格式响应消息子类派生成Rpc响应子类
    class RpcResponse : public JsonResponse {
    public:
        using ptr = std::shared_ptr<RpcResponse>;
        virtual bool check() override {
            // 修改前：
            // if (_msg_body[KEY_RCODE].isNull() == true || _msg_body[KEY_RCODE].isIntegral() == false){
            //     root_logger->ERROR("There is no response code field in the response or response code type error!");
            // 修改后：直接调用基类的接口判断响应码字段
            if (JsonResponse::check() == false) {
                return false;
            }
            if (_msg_body[KEY_RESULT].isNull() == true || _msg_body[KEY_RESULT].isObject() == false){
                root_logger->ERROR("RPC响应中缺少结果(result)或字段类型错误!");
                return false;
            }
            return true;
        }

        Json::Value getResult(){
            return _msg_body[KEY_RESULT];
        }
        void setResult(const Json::Value &result){
            _msg_body[KEY_RESULT] = result;
        }
    };

    // 由Json格式响应消息子类派生成主题响应子类
    class TopicResponse : public JsonResponse {
    public:
        using ptr = std::shared_ptr<TopicResponse>;
    };

    // 由Json格式响应消息子类派生成服务响应子类
    class ServiceResponse : public JsonResponse {
    public:
        using ptr = std::shared_ptr<ServiceResponse>;
        virtual bool check() override {
            // 修改前：
            // if (_msg_body[KEY_RCODE].isNull() == true || _msg_body[KEY_RCODE].isIntegral() == false){
            //     root_logger->ERROR("There is no response code field in the response or response code type error!");
            // 修改后：直接调用基类的接口判断响应码字段
            if (JsonResponse::check() == false) {
                return false;
            }
            if (_msg_body[KEY_OPTYPE].isNull() == true || _msg_body[KEY_OPTYPE].isIntegral() == false){
                root_logger->ERROR("服务响应中缺少操作类型(optype)或字段类型错误!");
                return false;
            }
            // 如果是服务发现响应 需要单独检测方法名和主机信息字段
            if (_msg_body[KEY_OPTYPE] == static_cast<int>(ServiceOpType::SERVICE_DISCOVERY) &&
                (_msg_body[KEY_METHOD].isNull() == true || _msg_body[KEY_METHOD].isString() == false ||
                     _msg_body[KEY_HOST].isNull() == true || _msg_body[KEY_HOST].isArray() == false)
            ){
                root_logger->ERROR("服务发现响应中缺少必要字段(method/host)或字段类型错误!");
                return false;
            }
            return true;
        }

        void setServiceOptype(const ServiceOpType &optype){
            _msg_body[KEY_OPTYPE] = static_cast<int>(optype);
        }
        ServiceOpType getServiceOpType(){
            return static_cast<ServiceOpType>(_msg_body[KEY_OPTYPE].asInt());
        }
        // 服务发现操作响应 需要单独处理的字段
        void setMethod(const std::string &method){
            _msg_body[KEY_METHOD] = method;
        }
        std::string getMethod(){
            return _msg_body[KEY_METHOD].asString();
        }
        void setHosts(const std::vector<Address> &hosts){
            for(auto &adds : hosts){
                Json::Value host_val;
                host_val[KEY_HOST_IP] = adds.first;
                host_val[KEY_HOST_PORT] = adds.second;
                _msg_body[KEY_HOST].append(host_val);
            }
        }
        std::vector<Address> getHosts(){
            std::vector<Address> hosts;
            for(auto &host_val : _msg_body[KEY_HOST]){
                Address adds;
                adds.first=host_val[KEY_HOST_IP].asString();
                adds.second = host_val[KEY_HOST_PORT].asInt();
                hosts.push_back(adds);
            }
            return hosts;
        }
    };


    // 通过工厂模式获取对应的消息对象
    class MessageFactory{
    public:
        static BaseMessage::ptr create(const MsgType &msgtype){
            switch(msgtype){
                case MsgType::REQ_RPC:
                    return std::make_shared<RpcRequest>();
                case MsgType::REQ_TOPIC:
                    return std::make_shared<TopicRequest>();
                case MsgType::REQ_SERVICE:
                    return std::make_shared<ServiceRequest>();
                case MsgType::RSP_RPC:
                    return std::make_shared<RpcResponse>();
                case MsgType::RSP_TOPIC:
                    return std::make_shared<TopicResponse>();
                case MsgType::RSP_SERVICE:
                    return std::make_shared<ServiceResponse>();
                default:
                    // 修改：不能实例化抽象基类，应返回空指针
                    return nullptr;
            }
        }

        template<typename MessageType, typename... Args>
        static std::shared_ptr<MessageType> create(Args &&... args){
            return std::make_shared<MessageType>(std::forward<Args>(args)...);
        }
    };
}